package cn.tedu._07springaop.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Arrays;

//切面类
//
@Aspect//该注解标识当前类为切面类
@Component
//当调用目标方法时，框架先检查有没有切面类，再检查有没有对应的切面方法
public class LogAspect {
    /*pointcut 注解，定义切入点表达式的方法*/
    @Pointcut("execution(public int cn.tedu._07springaop.aop.CalculatorImpl.*(..))")
    public void doTime(){}
    @Before("execution(public int cn.tedu._07springaop.aop.CalculatorImpl.*(..))")//（括号里的..代表是任意类型，任意数量的参数）
    //前置通知，调用目标方法【add(),sub(),mul(),div()之前需要执行的方法】
    //参数有为：切入点表达式，指定哪些方法需要被拦截植入扩展业务逻辑：
    public void beforeMethod(JoinPoint joinPoint){
        /*
        * joinPoint是连接点对象，即拦截到的目标方法的对象
        * 1获取方法名称： jointPoint.getSignature.getName（）
        * 2获取参数列表 jointPoint.getArgs（）*/
        String name = joinPoint.getSignature().getName();
       String  args = Arrays.toString(joinPoint.getArgs());
        //System.out.println(name+"xxx方法开始，参数为..." + args);
    }
    /*aftertrturning
    * 1返回通知：目标方法正常结束后执行，异常结束则不会执行
    * 2返回通知有权限获取目标方法的返回值*/
    @AfterReturning(value = "doTime()",returning = "result")//这个
   // @After("execution(public int cn.tedu._07springaop.aop.CalculatorImpl.*(..))")
    public void afterMethod(JoinPoint joinPoint,Object result){
        String name = joinPoint.getSignature().getName();
        System.out.println(name+"xxx方法结束");
    }
    /*afterthrowing
    * 1异常通知，目标方法抛出异常时执行
    * 2异常通知有权拿到目标方法抛出的异常对象*/
    @AfterThrowing(value = "doTime()", throwing = "e")
    public void afterThrowingMethod(JoinPoint jointPoint, Throwable e){
        String name = jointPoint.getSignature().getName();
        String data = e.getMessage();
        System.out.println(name+ "方法抛出异常，提示消息为"+ data);
    }
    /*环绕通知
    * around
    * 1环绕通知：等价于  前置通知 + 返回通知 + 后置通知 + 异常通知
    * 2环绕通知 有权执行目标方法！！！ 通常使用try()catch{} finally包裹*/
    @Around("doTime()")
    public Object aroundMethod(ProceedingJoinPoint joinPoint){
        Object result=null;
        try{
            //
            System.out.println("互绕通知：前置通知");
            result = joinPoint.proceed();
            //返回通知
            System.out.println("环绕通知： 返回通知");
        }catch (Throwable e){
            //异常通知
            System.out.println("环绕通知： 异常通知");
        }finally {
            //后置通知
            System.out.println("环绕通知： 后置通知");
        }
        return result;
    }
}























